
package adoc.xml;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.List;
import org.jdom.Document;
import org.jdom.Element;
import org.jdom.JDOMException;
import org.jdom.Namespace;
import org.jdom.input.SAXBuilder;
import org.jdom.xpath.*;

/**
 *
 * @author ILikePancakes
 */
public class SignedDocument extends Document {
    private Element root;
    private Namespace namespace = Namespace.getNamespace("http://www.archyvai.lt/adoc/2008/metadata/signable");
    private Calendar calendar = new GregorianCalendar();

    public SignedDocument() {
        super();
        root = new Element("metadata", namespace);
        root.setAttribute("ID", "metadata");
        this.setRootElement(root);
    }

    public SignedDocument(File file) throws IOException, JDOMException {
        super(new SAXBuilder().build(file).cloneContent());
        root = this.getRootElement();
    }

    public SignedDocument(String filename) throws IOException, JDOMException { this(new File(filename)); }

    public SignedDocument(String authorName, String address) {
        this();
        try {
            this.addAuthorData(authorName, address);
            this.addCreationData(getToday());
        } catch (JDOMException ex) {
            ex.printStackTrace();
        }
    }

    public SignedDocument(List<String> documentPaths) throws JDOMException, IOException {
        this();
        ArrayList<SignedDocument> documents = new ArrayList();
        for (String path : documentPaths) documents.add(new SignedDocument(path));
        for (SignedDocument document : documents) root.addContent(document.getRootElement().cloneContent());
    }

    private Element getElement(String xpathString) throws JDOMException {
        XPath xpath = XPath.newInstance(xpathString);
        xpath.addNamespace("n", namespace.getURI());
        List<Element> list = xpath.selectNodes(this);
        if (list != null) {
            switch(list.size()) {
                case 0 : return null;
                case 1 : return list.get(0);
                default: throw new JDOMException("daugiau nei vienas elementas");
            }
        }
        return null;
    }

    public Element getDocumentElement() throws JDOMException { return this.getElement("/n:metadata/n:document"); }
    public Element getAuthorsElement() throws JDOMException { return this.getElement("/n:metadata/n:authors"); }
    public Element getRecipientsElement() throws JDOMException { return this.getElement("/n:metadata/n:recipients"); }
    public Element getRegistrationsElement() throws JDOMException { return this.getElement("/n:metadata/n:registrations"); }
    public Element getReceptionsElement() throws JDOMException { return this.getElement("/n:metadata/n:receptions"); }

    private Element addToMetadata(String elementName) {
        Element element = new Element(elementName, namespace);
        root.addContent(element);
        return element;
    }

    public Element addDocumentData(String title, String sort) throws JDOMException {
        Element document = addToMetadata("document");
        document.setAttribute("ID", "document");
        Element titleElement = new Element("title", namespace);
        titleElement.setText(title);
        document.addContent(titleElement);
        if (sort != null) {
            Element sortElement = new Element("sort", namespace);
            titleElement.setText(sort);
            document.addContent(sortElement);
        }
        return document;
    }

    public Element addAuthorData(String authorName, String authorAddress) throws JDOMException {
        Element authors = getAuthorsElement();
        if (authors == null) { authors = addToMetadata("authors"); authors.setAttribute("ID", "authors"); }
        Element author = new Element("author", namespace);
        Element name = new Element("name", namespace);
        Element address = new Element("address", namespace);
        name.setText(authorName);
        address.setText(authorAddress);
        author.addContent(name);
        author.addContent(address);
        authors.addContent(author);
        author.setAttribute("ID", "author" + "_" + authors.getChildren().size());
        return author;
    }

    public Element addCreationData(String date) {
        Element creation = this.addToMetadata("creation");
        creation.setAttribute("ID", "creation");
        Element dateElement = new Element("date", namespace);
        dateElement.setText(date);
        creation.addContent(dateElement);
        return creation;
    }

    public Element addRecipientData(String recipientName, String recipientCode) throws JDOMException {
        Element recipients = this.getRecipientsElement();
        if (recipients == null) { recipients = addToMetadata("recipients"); recipients.setAttribute("ID", "recipients"); }
        Element recipient = new Element("recipient", namespace);
        Element name = new Element("name", namespace);
        Element code = new Element("code", namespace);
        name.setText(recipientName);
        code.setText(recipientCode);
        recipient.addContent(name);
        recipient.addContent(code);
        recipients.addContent(recipient);
        recipient.setAttribute("ID", "recipient" + "_" + recipients.getChildren().size());
        return recipient;
    }

    public Element addRegistrationData(String registrationDate, String registrationNumber) throws JDOMException {
        Element registrations = this.getRegistrationsElement();
        if (registrations == null) { registrations = addToMetadata("registrations"); registrations.setAttribute("ID", "registrations"); }
        Element registration = new Element("registration", namespace);
        Element date = new Element("data", namespace);
        Element number = new Element("number", namespace);
        date.setText(registrationDate);
        number.setText(registrationNumber);
        registration.addContent(date);
        registration.addContent(number);
        registrations.addContent(registration);
        registration.setAttribute("ID", "registration" + "_" + registrations.getChildren().size());
        return registration;
    }

    public Element addReceptionData(String receptionDate, String receptionNumber, String receiverName, String receiverCode, boolean individual)
            throws JDOMException {
        Element receptions = this.getReceptionsElement();
        if (receptions == null) { receptions = addToMetadata("receptions"); receptions.setAttribute("ID", "receptions"); }
        Element reception = new Element("reception", namespace);
        Element date = new Element("date", namespace);
        Element number = new Element("number", namespace);
        date.setText(receptionDate);
        number.setText(receptionNumber);
        reception.addContent(date);
        reception.addContent(number);
        Element receiver = new Element("receiver", namespace);
        receiver.setAttribute("ID", "receiver");
        reception.addContent(receiver);
        Element rcvName = new Element("name", namespace);
        Element rcvCode = new Element("code", namespace);
        Element rcvIndividual = new Element("individual", namespace);
        rcvName.setText(receiverName);
        rcvCode.setText(receiverCode);
        rcvIndividual.setText(String.valueOf(individual));
        receiver.addContent(rcvName);
        receiver.addContent(rcvCode);
        receiver.addContent(rcvIndividual);
        receptions.addContent(reception);
        reception.setAttribute("ID", "reception" +"_"+ receptions.getChildren().size());
        return reception;
    }

    private String getToday() {
        return g(Calendar.YEAR)+"-"+f(Calendar.MONTH)+"-"+f(Calendar.DAY_OF_MONTH)+"T"+f(Calendar.HOUR_OF_DAY)+":"+f(Calendar.MINUTE)+":"+f(Calendar.SECOND)+"Z";
    }
    private int g(int i) { return calendar.get(i); }
    private String f(int index) { int i = g(index); return ((i+"").length() == 1) ? "0"+i: i+""; }
}
